#include <parseconf.h>
#include <common.h>
#include <tunable.h>

void parseconf_load_file(const char *path)
{
	FILE *fp = fopen(path,"r");
	if(NULL == fp) {
		ERR_EXIT("fopen");
	}

	char setting_line[MAX_SET_LINE] = {0};
	while(fgets(setting_line,sizeof(setting_line),fp) != NULL) {
		//判断是否是合法的配置行
		if(strlen(setting_line) == 0 \
			|| setting_line[0] == '#' \
			|| regular_expression(setting_line,"m/^\\s+$/")) {
			continue;
		}
		regular_expression(setting_line,"s/\n//");
		//DEBUG_PRINT("setting_line:[%s]\n",setting_line);
		//还需要去掉左空格
		regular_expression(setting_line,"s/^\\s+//");
		//对配置进行读取操作
		parseconf_load_setting(setting_line);
		memset(setting_line,0,sizeof(setting_line));
	}
	fclose(fp);
}

static struct parseconf_bool_setting
{
  const char *p_setting_name;
  int *p_variable;
}
parseconf_bool_array[] =
{
	{ "pasv_enable", &tunable_pasv_enable },
	{ "port_enable", &tunable_port_enable },
	{ NULL, NULL }
};

static struct parseconf_uint_setting
{
	const char *p_setting_name;
	unsigned int *p_variable;
}
parseconf_uint_array[] =
{
	{ "listen_port", &tunable_listen_port },
	{ "max_clients", &tunable_max_clients },
	{ "max_per_ip", &tunable_max_per_ip },
	{ "accept_timeout", &tunable_accept_timeout },
	{ "connect_timeout", &tunable_connect_timeout },
	{ "idle_session_timeout", &tunable_idle_session_timeout },
	{ "data_connection_timeout", &tunable_data_connection_timeout },
	{ "local_umask", &tunable_local_umask },
	{ "upload_max_rate", &tunable_upload_max_rate },
	{ "download_max_rate", &tunable_download_max_rate },
	{ NULL, NULL }
};
static struct parseconf_str_setting
{
	const char *p_setting_name;
	const char **p_variable;
}
parseconf_str_array[] =
{
	{ "listen_address", &tunable_listen_address },
	{ NULL, NULL }
};

void parseconf_load_setting(const char *setting)
{
	//主要就是进行3个数组的遍历
	//将键值对分离出来
	char key[128] = {0};
	char value[128] = {0};
	str_split(setting,key,value,'=');
	if(0 == strlen(value)) {
		fprintf(stderr,"missing value in config file for: %s\n",key);
		exit(EXIT_FAILURE);
	}
	//遍历字符串类型配置项
	const struct parseconf_str_setting *p_str_setting = parseconf_str_array;
	while(p_str_setting->p_setting_name != NULL) {
		if(strcmp(key,p_str_setting->p_setting_name) == 0) {
			//说明找到了匹配的配置项
			const char **p_cur_setting = p_str_setting->p_variable;
			if(NULL != *p_cur_setting) {
				free((char *)*p_cur_setting);
			}
			//获取一个副本
			*p_cur_setting = strdup(value);
			return;
		}
		p_str_setting++;
	}
	//遍历开关类型配置项
	const struct parseconf_bool_setting *p_bool_setting = parseconf_bool_array;
	while(p_bool_setting->p_setting_name != NULL) {
		if(strcmp(key,p_bool_setting->p_setting_name) == 0) {
			str_upper(value);
			//说明找到了匹配的配置项
			//DEBUG_PRINT("val %s\n",value);
			if(0 == strcmp(value,"YES") || 0 == strcmp(value,"TRUE")
										|| 0 == strcmp(value,"1")) {
				*(p_bool_setting->p_variable) = 1;
			} else if(0 == strcmp(value,"NO") || 0 == \
				strcmp(value,"FALSE") || 0 == strcmp(value,"0")) {
				*(p_bool_setting->p_variable) = 0;
			} else {
				fprintf(stderr,"bad bool value in config file for: %s\n",key);
				exit(EXIT_FAILURE);
			}
			return;
		}
		p_bool_setting++;
	}
	//遍历整型类型的配置项
	const struct parseconf_uint_setting *p_uint_setting = parseconf_uint_array;
	while(p_uint_setting->p_setting_name != NULL) {
		if(strcmp(key,p_uint_setting->p_setting_name) == 0) {
			//需要注意的是，这个数字类型的可能有8进制方式的表示格式，需要进行转换
			*(p_uint_setting->p_variable) = abs(atoi_sint32_ex(value));
			return;
		}
		p_uint_setting++;
	}
}
